//
//  OpenSDK_WebView.m
//  Pods-Unity-iPhone
//
//  Created by 马乾征 on 2020/3/26.
//

#import "OpenSDK_WebView.h"
#import <JavaScriptCore/JavaScriptCore.h>

@interface OpenSDK_WebView() <WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler>
@property(nonatomic, copy)NSArray *jsMethods;
@property(nonatomic, weak)id<OpenSDK_WebView_Delegate> callbackDelegate;
@end

@implementation OpenSDK_WebView

- (instancetype)init
{
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.preferences.minimumFontSize = 0;
    config.preferences.javaScriptEnabled = YES;
    config.preferences.javaScriptCanOpenWindowsAutomatically = YES;
    config.allowsInlineMediaPlayback = YES;
    config.suppressesIncrementalRendering = YES;
    if (@available(iOS 10.0, *)) {
        config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
    } else {
        // Fallback on earlier versions
    }
    self = [super initWithFrame:CGRectZero configuration:config];
    if (self) {
        self.navigationDelegate = self;
        self.UIDelegate = self;
        [self setOpaque:NO];
        self.backgroundColor = [UIColor whiteColor];
        self.scrollView.bounces = NO;
        self.contentMode = UIViewContentModeScaleAspectFit;
        [self setHidden:YES];
    }
    return self;
}

-(id) initWithGetUrl:(NSString *) urlStr
           jsMethods:(NSArray *) methods
            callback:(id<OpenSDK_WebView_Delegate>) callback {
    self = [self init];
    _jsMethods = methods;
    _callbackDelegate = callback;
    // get方式
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
    [self loadRequest:request];
    return self;
}

-(id) initWithPostUrl:(NSString *) urlStr
             postBody:(NSString *) body
            jsMethods:(NSArray *) methods
             callback:(id<OpenSDK_WebView_Delegate>) callback {
    self = [self init];
    _callbackDelegate = callback;
    // post方式
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:urlStr]];
    [request setHTTPMethod: @"POST"];
    if (body) {
        [request setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
    }
    [self loadRequest:request];
    return self;
}

-(BOOL) isOpenAppSpecialURLValue:(NSString *)string {
    if ([string hasPrefix:@"http://"] || [string hasPrefix:@"https://"]) {
        return NO;
    }
    return YES;
}

+(void) openURL:(NSURL *)object complete:(void(^)(BOOL))complete {
    UIApplication *application = nil;
    application = [UIApplication sharedApplication];
    SEL selector = @selector(openURL:options:completionHandler:);
    if ([UIApplication instancesRespondToSelector:selector]) {
        if (@available(iOS 10.0, *)) {
            [application openURL:object
                         options:[NSDictionary dictionary]
               completionHandler:complete];
        } else {
            // Fallback on earlier versions
            if (complete) {
                complete([application openURL:object]);
            }
        }
        
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        if (complete) {
            complete([application openURL:object]);
        }
#pragma clang diagnostic pop
    }
}

// 注册 Message Name
- (void)addScriptMessageName:(NSArray *)names {
    for (NSString *name in names) {
        [self.configuration.userContentController addScriptMessageHandler:self name:name];
    }
}

#pragma mark - WKNavigationDelegate

// 1）接受网页信息，决定是否加载还是取消。必须执行回调 decisionHandler 。逃逸闭包的属性
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURL *url = navigationAction.request.URL;
    if ([self isOpenAppSpecialURLValue:url.absoluteString]) {
        //空白地址就直接返回不执行加载
        if ([url.absoluteString hasPrefix:@"about:blank"]) {
            decisionHandler(WKNavigationActionPolicyCancel);
        } else {
            //非http和https开头的链接就使用OpenURL方法打开
            [[self class] openURL:url complete:^(BOOL status) {
            }];
            decisionHandler(WKNavigationActionPolicyCancel);
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

// 2) 开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"网页开始加载 %s", __FUNCTION__);
}

// 3) 接受到网页 response 后, 可以根据 statusCode 决定是否 继续加载。allow or cancel, 必须执行回调 decisionHandler 。逃逸闭包的属性
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    decisionHandler(WKNavigationResponsePolicyAllow);
}

// 4) 网页加载成功
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"网页加载成功 %s", __FUNCTION__);
    [self setHidden:NO];
    if (_callbackDelegate != nil && [_callbackDelegate respondsToSelector:@selector(loadFinish:)]) {
        [_callbackDelegate loadFinish:YES];
    }
}

// 4) 网页加载失败
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"网页加载失败 %s", __FUNCTION__);
    if (_callbackDelegate != nil && [_callbackDelegate respondsToSelector:@selector(loadFinish:)]) {
        [_callbackDelegate loadFinish:YES];
    }
}

#pragma mark - WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:message preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:action];
    [[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:alertController animated:true completion:nil];
    completionHandler();
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
    completionHandler(YES);
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {
    completionHandler(prompt);
}

#pragma mark - WKScriptMessageHandler
//  JS发送消息
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSString *name = message.name;
    NSString *body = message.body;
    if(_callbackDelegate != nil && [_callbackDelegate respondsToSelector:@selector(callbackWithName:withArgs:)]) {
        [_callbackDelegate callbackWithName:name withArgs:body];
    }
}
@end
